package com.baofu.paycore.common.utils;

import com.alibaba.dubbo.rpc.RpcException;
import com.baofu.paycore.service.facade.enums.PayCoreErrorCode;
import com.baofu.paycore.service.facade.enums.PayStatusEnums;
import com.baofu.paycore.service.facade.model.PayBaseResDTO;
import com.system.commons.exception.BaseException;
import com.system.commons.exception.BizServiceException;
import com.system.commons.exception.CommonErrorCode;
import com.system.commons.exception.ErrorCode;
import com.system.commons.result.Result;
import com.baofu.paycore.common.exception.PayCoreBaseException;
import com.system.commons.utils.BeanCopyUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;

/**
 * 支付异常处理
 * <p>
 *     1、统一异常处理
 *     2、dubbo超时异常处理
 *     3、接口入口redis锁问题异常处理
 * </p>
 * User: 欧西涛 Date: 2015/09/06 ProductName: paycore Version: 5.0.0
 */
@Slf4j
public class ExceptionUtil {

    /**
     * 统一异常处理
     *
     * @param err 异常
     * @return 外部响应对象
     */
    public static <T> Result<T> doExceptionService(Throwable err,Class<T> clazz) {
        try {
            if (err instanceof PayCoreBaseException) {
                PayCoreBaseException e = (PayCoreBaseException) err;
                if (PayCoreErrorCodeUtil.payStatusHandler(e)) {
                    return buildRes(e.getErrorCode(), PayStatusEnums.FAIL.getCode(), true, clazz);
                }
                return buildRes(e.getErrorCode(), PayStatusEnums.INIT.getCode(), false, clazz);
            }

            if (err instanceof DuplicateKeyException) {
                return buildRes(PayCoreErrorCode.UNIQUE_ERROR, PayStatusEnums.FAIL.getCode(), true, clazz);
            }
            if (err instanceof BizServiceException) {

                BizServiceException e = (BizServiceException) err;
                String errorMsg = (StringUtils.isBlank(e.getExtraMsg()) ?
                        e.getErrorCode().getErrorDesc() : e.getExtraMsg());
                if (PayCoreErrorCode.REDIS_LOCK_ERROR.getErrorCode().equals(e.getErrorCode().getErrorCode())) {
                    return buildRes(PayCoreErrorCode.REDIS_LOCK_ERROR, PayStatusEnums.INIT.getCode(), false, clazz);
                }
                ErrorCode errorCode = e.getErrorCode();
                errorCode.setErrorDesc(errorMsg);
                if (PayCoreErrorCodeUtil.payStatusHandler(e)) {
                    return buildRes(errorCode, PayStatusEnums.FAIL.getCode(), true, clazz);
                }
                return buildRes(errorCode, PayStatusEnums.INIT.getCode(), false, clazz);
            }
        } catch (Exception e) {
            log.error("call ExceptionUtil doExceptionService：{}", e);
        }
        return buildRes(CommonErrorCode.SYSTEM_INNER_ERROR, PayStatusEnums.INIT.getCode(), false, clazz);
    }

    /**
     * 统一处理异常
     *
     * @param err 异常
     * @return 外部响应对象
     */
    public static <T> Result<T> doQueryExceptionService(Throwable err, Class<T> clazz) {
        try {
            if (err instanceof PayCoreBaseException) {
                PayCoreBaseException e = (PayCoreBaseException) err;
                return buildRes(e.getErrorCode(), PayStatusEnums.INIT.getCode(), false, clazz);
            }
            if (err instanceof BizServiceException) {
                BizServiceException e = (BizServiceException) err;
                return buildRes(e.getErrorCode(), PayStatusEnums.INIT.getCode(), false, clazz);
            }
        } catch (Exception e) {
            log.error("call ExceptionUtil doQueryExceptionService：{}", e);
        }
        return buildRes(CommonErrorCode.SYSTEM_INNER_ERROR, PayStatusEnums.INIT.getCode(), false, clazz);

    }

    private static  <T> Result<T> buildRes(ErrorCode errorCode, String status, boolean flag, Class<T> clazz){
        PayBaseResDTO clearBaseRes = new PayBaseResDTO();
        clearBaseRes.setErrorCode(errorCode.getErrorCode());
        clearBaseRes.setErrorMsg(errorCode.getErrorDesc());
        clearBaseRes.setRealRtnFlag(flag);
        clearBaseRes.setStatus(status);
        return new Result<>(BeanCopyUtil.objConvert(clearBaseRes, clazz));
    }

    /**
     * 统一异常处理
     *
     * @param err 异常
     * @return 外部响应对象
     */
    public static <T> Result<T> doExceptionService(Throwable err) {
        try {

            if (err instanceof IllegalArgumentException) {
                return new Result<>(CommonErrorCode.PARAMETER_FIELD_VALID_NOT_PASS);
            }

            if (err instanceof BizServiceException) {
                BizServiceException e = (BizServiceException) err;
                return new Result<>(e.getErrorCode().getErrorCode(),e.getErrorCode().getErrorDesc());
            }
            if (err instanceof PayCoreBaseException) {
                PayCoreBaseException e = (PayCoreBaseException) err;
                return new Result<>(e.getErrorCode().getErrorCode(),e.getErrorCode().getErrorDesc());
            }

        } catch (Exception e) {
            log.error("call ExceptionUtil doExceptionService：{}", e);
        }
        return new Result<>(CommonErrorCode.SYSTEM_INNER_ERROR.getErrorCode(),CommonErrorCode.SYSTEM_INNER_ERROR.getErrorDesc());
    }

    /**
     * 2、dubbo超时异常处理
     *
     * @param exception 异常
     * @return 外部响应对象
     */
    public static Boolean dealTimeOutException(Exception exception){

        if(exception instanceof RpcException){
            RpcException rpcException = (RpcException)exception;
            if(rpcException.isTimeout()){
                return true;
            }
        }
        return false;
    }

}
